package fotel

import (
	"context"

	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
	"go.opentelemetry.io/otel/exporters/prometheus"
	"go.opentelemetry.io/otel/propagation"
	sdkmetric "go.opentelemetry.io/otel/sdk/metric"
	"go.opentelemetry.io/otel/sdk/resource"
	tracesdk "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.32.0"
)

var (
	isTracerInit    bool // 	是否已初始otel链路追踪
	isMeterProvider bool // 是否初始化otel指标上传
)

func init() {
	// 上下文传播
	otel.SetTextMapPropagator(
		propagation.NewCompositeTextMapPropagator(
			propagation.TraceContext{},
			propagation.Baggage{},
		),
	)
}

// 采用opentelemetry的方式 初始化链路追踪
func InitTracer(endpoint, serviceName string) error {
	// 汇总配置
	traceOpts := []tracesdk.TracerProviderOption{
		// 将基于父span的采样率设置为100%
		tracesdk.WithSampler(
			tracesdk.ParentBased(tracesdk.TraceIDRatioBased(1.0)),
		),
		// 在资源中记录有关此应用程序的信息
		tracesdk.WithResource(resource.NewSchemaless(
			semconv.ServiceNameKey.String(serviceName),
			attribute.String("exporter", "otlp"),
		)),
	}
	// local标识为： 没有链路追踪的服务，但是可以开启追踪，用于串联日志。
	if endpoint != "local" {
		// 创建 exporter
		exporter, err := otlptracehttp.New(context.Background(),
			otlptracehttp.WithEndpoint(endpoint),
			otlptracehttp.WithInsecure(),
		)
		if err != nil {
			return err
		}
		// 始终确保在生产中批量处理
		traceOpts = append(traceOpts, tracesdk.WithBatcher(
			exporter,
		))
	}
	// 创建追踪资源
	tp := tracesdk.NewTracerProvider(
		traceOpts...,
	)
	otel.SetTracerProvider(tp)
	isTracerInit = true
	return nil
}

// 采用opentelemetry的方式 初始化监控
func InitMeterProvider() error {
	exporter, err := prometheus.New()
	if err != nil {
		return err
	}
	provider := sdkmetric.NewMeterProvider(sdkmetric.WithReader(exporter))
	// 将其注册为全局 MeterProvider，以便通过 otel.Meter 和 otel.GetMeterProvider 获取
	// 大多数自动插桩库都默认使用全局 MeterProvider，若未设置则会退化为 no-op 实现，
	// 此时，不会产生任何数据。
	otel.SetMeterProvider(provider)
	isMeterProvider = true
	return nil
}

// 获取 tracer 初始化状态
func GetTracerStatus() bool {
	return isTracerInit
}

// 获取 Meter 初始化状态
func GetMeterProviderStatus() bool {
	return isMeterProvider
}
